package iha.auh.kds.aba.painratingapp;

import iha.auh.kds.aba.painratingapp.Models.ChildModel;
import iha.auh.kds.aba.painratingapp.Models.PainScoringModel;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;

public class DataService extends Service {
	private String serviceArg; 
	private String httpMethod;
	
	public static final String VALIDATE_CPR = "iha.auh.kds.aba.painratingapp.ValidateCPR";
	public static final String SAVE_RATING = "iha.auh.kds.aba.painratingapp.SaveRating";
	public static final String GET_PAIN_RATINGS = "iha.auh.kds.aba.painratingapp.GetPainRatings";
	
	public DataService() {
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		String validateCPRUrl = intent.getExtras().getString("validate_cpr_url");
		String saveRatingUrl = intent.getExtras().getString("save_rating_url");
		String getPainRatingsUrl = intent.getExtras().getString("get_pain_ratings_url");
		httpMethod = intent.getExtras().getString("http_method");
		
		if (validateCPRUrl != null) {
			serviceArg = "validate_cpr_url";
			new getDataAsync().execute(validateCPRUrl);
		} else if (saveRatingUrl != null) {
			serviceArg = "save_rating_url";
			new getDataAsync().execute(saveRatingUrl);
		} else if (getPainRatingsUrl != null) {
			serviceArg = "get_pain_ratings_url";
			new getDataAsync().execute(getPainRatingsUrl);
		}
		
		return Service.START_NOT_STICKY;
	}
	
	public void postData(String url) {
		HttpClient httpClient = new DefaultHttpClient();
		HttpPost postMethod = new HttpPost(url);
		HttpResponse webServerResponse = null;
		
		try {
			webServerResponse = httpClient
					.execute(postMethod);
		} catch (ClientProtocolException e) {
			// Deal with exception
		} catch (IOException e) {
			// Deal with exception
		}
		
		int statusCode = webServerResponse
				.getStatusLine().getStatusCode();
		
		if(serviceArg.equals("save_rating_url")) {
			Intent dataReadyBroadcast = new Intent(SAVE_RATING);
			
			if (statusCode == 200)
				dataReadyBroadcast.putExtra("response", "success");
			else
				dataReadyBroadcast.putExtra("response", "failure");
			
			LocalBroadcastManager.getInstance(this).sendBroadcast(dataReadyBroadcast);
		}
	}
	
	public void getData(String url) {
		// Code is from handin
		String result = null;
		URI uri = null;
		
		try {
			uri = new URI(url);
		} catch (URISyntaxException e) {
			// Deal with exception
		}
		
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet getMethod = new HttpGet(uri);
		HttpResponse webServerResponse = null;
		
		try {
			webServerResponse = httpClient.execute(getMethod);
		} catch (ClientProtocolException e) {
			// Deal with exception
		} catch (IOException e) {
			// Deal with exception
		}
		
		HttpEntity httpEntity = webServerResponse.getEntity();
		
		if (httpEntity != null) {
			InputStream instream;
			
			try {
				instream = httpEntity.getContent();
				result = convertStreamToString(instream);
				instream.close();
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if(serviceArg.equals("validate_cpr_url")) {
			ChildModel child;
			
			try {
				JSONObject jsonChild = new JSONObject(result).getJSONObject("response");
				child = convertJSONToModel(jsonChild);
			} catch (JSONException e) {
				child = new ChildModel();
				e.printStackTrace();
			}
			
			ChildSingleton.setChild(child);
			
			Intent dataReadyBroadcast = new Intent(VALIDATE_CPR);
			
			if (child.ID != 0)
				dataReadyBroadcast.putExtra("response", "success");
			else
				dataReadyBroadcast.putExtra("response", "failure");
			
			LocalBroadcastManager.getInstance(this).sendBroadcast(dataReadyBroadcast);
		} else if (serviceArg.equals("save_rating_url")) {
			Intent dataReadyBroadcast = new Intent(SAVE_RATING);
			String response = "";
			
			try {
				response = new JSONObject(result).getString("response");
			} catch (JSONException e) {
				e.printStackTrace();
			}
			
			if (response.equalsIgnoreCase("Accepted"))
				dataReadyBroadcast.putExtra("response", "success");
			else if (response.equalsIgnoreCase("NotAcceptable"))
				dataReadyBroadcast.putExtra("response", "failure");
			
			LocalBroadcastManager.getInstance(this).sendBroadcast(dataReadyBroadcast);
		} else if (serviceArg.equals("get_pain_ratings_url")) {
			ArrayList<PainScoringModel> painScoringArray = new ArrayList<PainScoringModel>();
			
			try {
				JSONArray jsonPainScoringArray = new JSONObject(result).getJSONObject("response").getJSONArray("PainScoring");
				
				for(int i = 0; i < jsonPainScoringArray.length(); i++) {
					JSONObject tmp = jsonPainScoringArray.getJSONObject(i);
					painScoringArray.add(convertPainScoringJSONToModel(tmp));
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
			
			ChildSingleton.getChild().PainScoring = painScoringArray;
			
			Intent dataReadyBroadcast = new Intent(GET_PAIN_RATINGS);
			
			if (painScoringArray.size() > 0)
				dataReadyBroadcast.putExtra("response", "success");
			else
				dataReadyBroadcast.putExtra("response", "failure");
			
			LocalBroadcastManager.getInstance(this).sendBroadcast(dataReadyBroadcast);
		}
	}
	
	private class getDataAsync extends AsyncTask<String, Integer, Long> {
		@Override
		protected Long doInBackground(String... urls) {
			if (httpMethod != null && httpMethod.equals("post"))
				postData(urls[0]);
			else
				getData(urls[0]);
			
			return null;
		}
	}
	
	private ChildModel convertJSONToModel(JSONObject object) {
		ChildModel model;
		
		try {
			model = new ChildModel(
					object.getInt("ID"),
					object.getString("CPR"),
					object.getString("Name"));
		} catch (JSONException e) {
			e.printStackTrace();
			model = new ChildModel();
		}
		
		return model;
	}
	
	private PainScoringModel convertPainScoringJSONToModel(JSONObject object) {
		PainScoringModel model;
		
		try {
			model = new PainScoringModel(
					object.getInt("ID"),
					object.getInt("PainRating"),
					object.getString("Note"),
					object.getString("Date"));
		} catch (JSONException e) {
			e.printStackTrace();
			model = new PainScoringModel();
		}
		
		return model;
	}
	
	private String convertStreamToString(InputStream is) throws IOException {
		if (is != null) {
			StringBuilder sb = new StringBuilder();
			String line = null;
 
			try {
				BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
				while ((line = reader.readLine()) != null) {
					sb.append(line).append("\n");
				}
			} finally {
				is.close();
			}
			
			return sb.toString();
		} else {
			return "";
		}
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		// TODO: Return the communication channel to the service.
		throw new UnsupportedOperationException("Not yet implemented");
	}
}
